/*
 * Copyright 2023 Away、尘
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <stdio.h>
#include <string.h>

#include "cmsis_os2.h"
#include "ohos_init.h"

#include "pressed_event.h"
#include "led_control.h"
#include "wifi_connect.h"
#include "oc_mqtt.h"
#include "oc_mqtt_profile_package.h"

#define WIFI_SSID ""    //WIFI名称
#define WIFI_PASSWD ""  //WIFI密码

#define MSG_QUEUE_SIZE 5
#define MSG_QUEUE_BYTE_OF_ELEMENT 128
#define CLIENT_ID ""
#define USERNAME ""
#define PASSWORD ""

#define TASK_DELAY_TIME 100

void F1PressedEvent(void){
    printf("led state: %d\n", GetLedState());
    if(GetLedState() == ON){
        printf("led off\n");
        LedOff();
    }else{
        printf("led on\n");
        LedOn();
    }
}

static void ButtonControlLed(){
    LedInit();
    F1Init();
    SetF1PressedEvent(F1PressedEvent);
}

static osMessageQueueId_t *MsgQueue;
static connect = 0;

int containStr(char *str, char *substr){
    char *p = strstr(str, substr);
    if(p == NULL){
        return 0;
    }
    return 1;
}
typedef struct{
    char *request_id;
    int type;// 1:LightOn, 2:LightOff, 3:GetLightState
}cmd_t;
int flag = 0;

oc_mqtt_profile_service_t * getService(const char *service_id){
    oc_mqtt_profile_service_t *service = (oc_mqtt_profile_service_t *)malloc(sizeof(oc_mqtt_profile_service_t));
    if(strcmp(service_id,"light") == 0){
        service->event_time = NULL;
        service->service_id = service_id;
        oc_mqtt_profile_kv_t *led = (oc_mqtt_profile_kv_t *)malloc(sizeof(oc_mqtt_profile_kv_t));
        int *LightState = (int *)malloc(sizeof(int));
        *LightState = GetLedState();
        led->key="LightState";
        led->value =LightState;
        led->type = EN_OC_MQTT_PROFILE_VALUE_INT;
        led->nxt = NULL;
        service->service_property = led;
        service->nxt = NULL;
    }else{
        printf("[ERROR] getService failed to get service, beacause service_id is not light.\n");
        free(service);
        return NULL;
    }
    return service;
}

void destoryService(oc_mqtt_profile_service_t *service){
    oc_mqtt_profile_service_t *serviceTmp = service;
    while(serviceTmp!=NULL){
        oc_mqtt_profile_kv_t *kv = service->service_property;
        while(kv!=NULL){
            oc_mqtt_profile_kv_t *tmp = kv;
            kv = kv->nxt;
            free(tmp->value);
            free(tmp);
        }
        oc_mqtt_profile_service_t *tmp = serviceTmp;
        serviceTmp = serviceTmp->nxt;
        free(tmp);
    }
}

void mqtt_event_handler(uint8_t *recv_data, uint32_t recv_size, uint8_t **resp_data, uint32_t *resp_size){
    cmd_t *cmd = (cmd_t *)malloc(sizeof(cmd_t));
    recv_data[recv_size] = '\0';
    printf("[INFO] recive command:%s\n",recv_data);
    if(containStr(recv_data,"LightOn")){
        cmd->type = 1;
        printf("[INFO] command: LightOn\n");
    }else if(containStr(recv_data,"LightOff")){
        cmd->type = 2;
        printf("[INFO] command: LightOff\n");
    }else if(containStr(recv_data,"GetLightState")){
        cmd->type = 3;
        printf("[INFO] command: GetLightState\n");
    }
    char *request_id = get_last_request_id();
    if(request_id == NULL){
        printf("[ERROR] mqtt_event_handler failed to get request_id.\n");
        return;
    }
    cmd->request_id = request_id;
    osMessageQueuePut(MsgQueue,&cmd,0U,0U);
}

void DealCommand(cmd_t *cmd){
    oc_mqtt_profile_cmdresp_t cmdresp;
    int LightState = GetLedState();
    oc_mqtt_profile_kv_t led;
    if(cmd == NULL){
        printf("[ERROR] DealCommand failed to deal command, beacause cmd is NULL.\n");
        return;
    }
    if(cmd->type == 1){
        LedOn();
        cmdresp.paras = NULL;
        cmdresp.request_id = cmd->request_id;
        cmdresp.ret_code = 0;
        cmdresp.ret_name = NULL;
    }else if(cmd->type == 2){
        LedOff();
        cmdresp.paras = NULL;
        cmdresp.request_id = cmd->request_id;
        cmdresp.ret_code = 0;
        cmdresp.ret_name = NULL;
    }else if(cmd->type == 3){
        led.key="LightState";
        led.value =&LightState;
        led.type = EN_OC_MQTT_PROFILE_VALUE_INT;
        led.nxt = NULL;
        cmdresp.paras = &led;
        cmdresp.request_id = cmd->request_id;
        cmdresp.ret_code = 0;
        cmdresp.ret_name = NULL;
    }

    oc_mqtt_profile_cmdresp(USERNAME, &cmdresp);
}

void MqttInit(){
    device_info_init(CLIENT_ID, USERNAME, PASSWORD);
    MsgQueue = osMessageQueueNew(MSG_QUEUE_SIZE, MSG_QUEUE_BYTE_OF_ELEMENT, NULL);
    int ret = oc_mqtt_init();
    if(ret != 0 ){
        printf("[ERROR] MqttInit failed to init mqtt. errcode:%d\n",ret);
        return ;
    }
    oc_set_cmd_rsp_cb(mqtt_event_handler);
    connect = 1;
    printf("[INFO] MqttInit successed to connect to server.\n");
}

void MqttReport(void){
    if(connect == 0){
        printf("[ERROR] MqttReport failed to report, beacause mqtt is not connected.\n");
        return;
    }
    //printf("[DEBUG] MqttReport report.\n");
    oc_mqtt_profile_service_t *service = getService("light");
    //printf("[DEBUG] after getService.\n");
    int ret = oc_mqtt_profile_propertyreport(USERNAME, service);
    //printf("[DEBUG] oc_mqtt_profile_propertyreport.\n");
    destoryService(service);
    //printf("[DEBUG] destoryService.\n");
    if(ret != 0){
        printf("[ERROR] MqttReport failed to report. errcode:%d\n",ret);
    }
    //printf("[INFO] MqttReport successed to report.\n");
    
}


static void MqttConrtrolLed(void){
    if(WifiConnect(WIFI_SSID, WIFI_PASSWD)!=0){
        printf("[ERROR] MqttConrtrolLed failed to start, beacause wifi failed to connect.\n");
        return;
    }
    MqttInit();
    cmd_t *cmd;
    while(1){
        cmd = NULL;
        //MqttReport();
        osMessageQueueGet(MsgQueue,(void **)&cmd,NULL,0U);
        if(cmd!=NULL){
            DealCommand(cmd);
            free(cmd);
        }else{
            MqttReport();
        }
        osDelay(TASK_DELAY_TIME);
    }
}

static void SmartLed(void){
    osThreadAttr_t attr;
    attr.name = "MqttConrtrolLed";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size =  (1024 * 10);
    attr.priority = 24;
    if (osThreadNew((osThreadFunc_t)MqttConrtrolLed, NULL, &attr) == NULL) {
        printf("Failed to create MqttReportTask!\n");
    }
    attr.name = "ButtonControlLed";
    attr.priority = 23;
    attr.stack_size =  (1024 * 2);
    if (osThreadNew((osThreadFunc_t)ButtonControlLed, NULL, &attr) == NULL) {
        printf("Failed to create MqttReportTask!\n");
    }
}
APP_FEATURE_INIT(SmartLed);